package com.fitso.model.bean.nutrition;

import java.io.Serializable;

import org.apache.commons.lang.builder.EqualsBuilder;
import org.apache.commons.lang.builder.HashCodeBuilder;
import org.apache.commons.lang.builder.ReflectionToStringBuilder;

import com.fitso.model.bean.ModelBean;
import com.fitso.model.bean.measure.Measure;
import com.fitso.model.bean.measure.energy.Calorie;
import com.fitso.model.bean.measure.mass.Gram;
import com.fitso.model.bean.measure.mass.Mass;

/**
 * <p>
 * A nutrient is food or chemicals that an organism needs to live and grow or a
 * substance used in an organism's metabolism which must be taken in from its
 * environment
 * </p>
 * <p>
 * Adapter around the {@link Measure} {@link Mass} interfaces which facilitates
 * type safe implementations that have the same basic behavior; such as
 * {@link Carbohydrate}, {@link Fat} and {@link Protein}, etc...
 * </p>
 * 
 * @author timothy storm
 * @see <a href="http://en.wikipedia.org/wiki/Nutrient">Nutrient</a>
 */
public abstract class Nutrient extends ModelBean implements Serializable {
	// Only change on breaking changes, i.e., removing fields
	private static final long serialVersionUID = 1L;
	
	private Mass _mass;

	public Nutrient() {}

	public Nutrient(Mass mass) {
		_mass = mass;
	}

	public boolean equals(final Object o) {
		if (o instanceof Nutrient == false) {
			return false;
		}
		if (this == o) {
			return true;
		}

		Nutrient other = (Nutrient) o;
		return new EqualsBuilder().append(_mass, other._mass).isEquals();
	}

	public Calorie getCalories() {
		Calorie caloriesPerGram = new Calorie(getCaloriesPerGram().getValue());
		Gram totalGrams = new Gram(getMass());
		
		return (Calorie) caloriesPerGram.multiply(totalGrams);
	}
	abstract protected Calorie getCaloriesPerGram();

	public Mass getMass() {
		return _mass;
	}

	public int hashCode() {
		return new HashCodeBuilder().append(_mass).append(this.getClass().getName()).toHashCode();
	}

	protected Nutrient setMass(Mass mass) {
		_mass = mass;
		return this;
	}

	public String toString() {
		return new ReflectionToStringBuilder(this).toString();
	}
}
